package pk232guru;

import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
//import java.util.Arrays;
//import javax.swing.SwingUtilities;
//import javax.swing.SwingWorker;
import java.util.regex.*;

public class pk232comms {

    public pk232comms() {
        super();
    }
    static public SerialPort serialPort;
    static public OutputStream outStream;
    static public InputStream inStream;

    void connect(String portName, String portStopbits, String portParity, String portDatabits, String portBaudrate) throws Exception {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if (portIdentifier.isCurrentlyOwned()) {
            System.out.println("Error: Port is currently in use");
        } else {
            CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);

            if (commPort instanceof SerialPort) {
                int localStopbits;
                int localParity;
                serialPort = (SerialPort) commPort;
                switch (portStopbits) {
                    case "1.5":
                        localStopbits = 3;
                        break;
                    case "2":
                        localStopbits = 2;
                        break;
                    default:
                        localStopbits = 1;
                        break;
                }

                switch (portParity) {
                    case "Even":
                        // Parity: Even
                        localParity = 2;
                        break;
                    case "Mark":
                        // Parity: Mark
                        localParity = 3;
                        break;
                    case "Odd":
                        // Parity: Odd
                        localParity = 1;
                        break;
                    case "Space":
                        // Parity: Space
                        localParity = 4;
                        break;
                    default:
                        // Parity: None
                        localParity = 0;
                        break;
                }

                serialPort.setSerialPortParams(Integer.parseInt(portBaudrate), Integer.parseInt(portDatabits), localStopbits, localParity);
                serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
                serialPort.setRTS(true);
                serialPort.setDTR(true);
                inStream = serialPort.getInputStream();
                outStream = serialPort.getOutputStream();

                (new Thread(new SerialWriter(outStream))).start();

                serialPort.addEventListener(new SerialReader(inStream));
                serialPort.notifyOnDataAvailable(true);
            } else {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }
    }

    public static class SerialReader implements SerialPortEventListener {

        private InputStream in;
        private byte[] buffer = new byte[1024];

        public SerialReader(InputStream in) {
            this.in = in;
        }

        public void serialEvent(SerialPortEvent arg0) {
            int data;
            Pattern p = Pattern.compile("cmd:");
            String lineFromPk232;
            int len = 0;
            try {
                while ((data = in.read()) > -1) {
                    if ((pk232guru.hostMode == false) && ((data == 10) || (data == 13))) {
                        if (data == 10) {
                            buffer[len++] = 10;
                        }
                        System.out.println("Not in host mode, and rec'd a CR or LF");
                        break;
                    }
                    if (data == 23) {
                        System.out.println("\nFound data==23");
                        if ((pk232guru.hostMode == true) && (pk232guru.getCWspeed == true)) {
                            System.out.println("Trying to get CW speed");
                            pk232guru.getCWspeed = false;
                            char firstChar = (char) buffer[4];
                            char secondChar = (char) buffer[5];
                            String cwspeed2write = "";
                            cwspeed2write = new StringBuffer(cwspeed2write).append(firstChar).toString();
                            cwspeed2write = new StringBuffer(cwspeed2write).append(secondChar).toString();
                            pk232guru.cwSpeed = Integer.parseInt(cwspeed2write);
                            pk232guru.jToggleButtonMOauto.setEnabled(true);
                            break;
                        } else if ((pk232guru.hostMode == true) && (pk232guru.getOpMode == true)) {
                            System.out.println("In host mode getting opmode");
                            if ((buffer[4] == 'M') && (buffer[5] == 'O')) {
                                System.out.println("Found Morse/CW mode");
                                pk232guru.jRadioButtonModeMO.setSelected(true);
                                char firstChar = (char) buffer[7];
                                char secondChar = (char) buffer[8];
                                String cwspeed2write = "";
                                cwspeed2write = new StringBuffer(cwspeed2write).append(firstChar).toString();
                                cwspeed2write = new StringBuffer(cwspeed2write).append(secondChar).toString();
                                pk232guru.cwSpeed = Integer.parseInt(cwspeed2write);
                                pk232guru.jLabelCWspeed.setText(cwspeed2write);
                                pk232guru.getOpMode = false;
                                pk232guru.jSliderCWspeed.setValue(pk232guru.cwSpeed);
                                pk232guru.jToggleButtonMOauto.setEnabled(true);
                                break;
                            } else if (buffer[4] == 'P') {
                                if (buffer[5] == 'A') {
                                    System.out.println("Found packet mode");
                                    pk232guru.jRadioButtonModePA.setSelected(true);
                                    pk232guru.getOpMode = false;
                                    pk232guru.jToggleButtonMOauto.setEnabled(false);
                                    break;
                                } else if (buffer[5] == 't') {
                                    System.out.println("Found Pactor mode");
                                    pk232guru.jRadioButtonModePT.setSelected(true);
                                    pk232guru.getOpMode = false;
                                    pk232guru.jToggleButtonMOauto.setEnabled(false);
                                    break;
                                } else {
                                    System.out.println("Found mode? P???" + buffer[5]);
                                    pk232guru.getOpMode = false;
                                    break;
                                }
                            } else if ((buffer[4] == 'B') && (buffer[5] == 'A')) {
                                System.out.println("Found Baudot RTTY mode");
                                pk232guru.jRadioButtonModeBA.setSelected(true);
                                pk232guru.getOpMode = false;
                                pk232guru.jToggleButtonMOauto.setEnabled(false);
                                break;
                            } else if (buffer[4] == 'A') {
                                if (buffer[5] == 'S') {
                                    System.out.println("Found Ascii RTTY mode");
                                    pk232guru.jRadioButtonModeAS.setSelected(true);
                                    pk232guru.getOpMode = false;
                                    pk232guru.jToggleButtonMOauto.setEnabled(false);
                                    break;
                                } else if (buffer[5] == 'M') {
                                    System.out.println("Found Amtor mode");
                                    pk232guru.jRadioButtonModeAM.setSelected(true);
                                    pk232guru.getOpMode = false;
                                    pk232guru.jToggleButtonMOauto.setEnabled(false);
                                    break;
                                } else {
                                    System.out.println("Found mode:  A???" + buffer[5]);
                                    pk232guru.getOpMode = false;
                                    break;
                                }
                            } else {
                                System.out.println("Couldn't get the mode?: [" + new String(buffer, 0, len) + "]");
                                pk232guru.getOpMode = false;
                                break;
                            }
                            // End of getOpMode
                        } else if ((pk232guru.hostmodeDesired == true) && (pk232guru.hostMode == false) && (buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 71) && (buffer[3] == 71) && (buffer[4] == 0)) {
                            pk232guru.hostMode = true;
                            pk232guru.hostmodeDesired = false;
                            System.out.println("We are in HOST mode");
                            break;
                        }  else if ((pk232guru.cwXmit == false) && (buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 88) & (buffer[3] == 77) && (buffer[4] == 0)) {
                            // Got our response back, we're in CW xmit
                            System.out.println("We are in CW xmit");
                            pk232guru.cwXmit = true;
                            break;
                        } else if ((buffer[0] == 1) && (buffer[1] == 95) && (buffer[2] == 88) && (buffer[3] == 88) && (buffer[4] == 0)) {
                            // Data ack
                            System.out.println("Data acknowledged");
                            pk232guru.cwACKwait = true;
                            break;
                        } else if ((buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 82) & (buffer[3] == 67) && (buffer[4] == 0)) {
                            System.out.println("Back in receive mode");
                            break;
                        } else if ((buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 88) && (buffer[3] == 77) && (buffer[4] == 0)) {
                            System.out.println("In Transmist, but cwXmit was true");
                            break;
                        } else if ((pk232guru.dataFinished == false) && (buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 71) && (buffer[3] == 71) && (buffer[4] == 0)) {
                            pk232guru.dataFinished = true;
                            System.out.println("Received data ack");
                            break;
                        } else if (pk232guru.hostMode == true) {
                            for (int i = 0; i < len; i++) {
                                System.out.print("[" + buffer[i] + "]");
                            }
                            System.out.println();
                            pk232guru.jTextAreaSerialIn.append(new String(buffer, 1, 0).toString());
                            break;
                        } else {
                            System.out.println("Found 23 on end, but don't know why, and we're not in HOST mode");
                            break;
                        }
                        //if ((pk232guru.dispOPmode == true) && (data == 23) && (buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 'O') && (buffer[3] == 'P')) {
                        //    pk232guru.dispOPmode = false;
                        //    buffer[len++] = 0;
                        //    buffer[len++] = 0;
                        //    buffer[len++] = 0;
                        //    System.out.println(new String(buffer, 4, len));
                        //    break;
                        //}
                        // In Host mode if receive $01, $4F, $47, $47, $00, $17
                    } else if (data == 47) {
                        System.out.println("Found a $2F");
                    } else {
                        System.out.print("[" + data + "]");
                    }
                    buffer[len++] = (byte) data;
                }
                //System.out.println(new String(buffer, 0, len));
                if ((pk232guru.convMode == false) && (len >= 3) && (pk232guru.hostMode == false)) {
                    String cmdNoCrLf = new String(buffer, 0, len);
                    Matcher m = p.matcher(cmdNoCrLf);
                    if (m.matches()) {
                        pk232guru.convMode = true;
                        System.out.println("Found cmd:");
                    }
                }
                // In Host mode if receive $01, $4F, $47, $47, $00, $17
                if ((pk232guru.hostmodeDesired == true) && (pk232guru.hostMode == false) && (buffer[0] == 1) && (buffer[1] == 79) && (buffer[2] == 71) && (buffer[3] == 71) && (buffer[4] == 0) && (buffer[5] == 23)) {
                    pk232guru.hostMode = true;
                    pk232guru.hostmodeDesired = false;
                }
                pk232guru.jTextAreaSerialIn.append(new String(buffer, 2, 1));
                pk232guru.jTextAreaSerialIn.setCaretPosition(pk232guru.jTextAreaSerialIn.getText().length());
                for(int i = 0; i < buffer.length; i++) {
                    buffer[i] = (byte) 255;
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
        }
    }

    public static class SerialWriter implements Runnable {

        OutputStream out;

        public SerialWriter(OutputStream out) {
            this.out = out;
        }

        public void run() {
            try {
                int c = 0;
                while ((c = System.in.read()) > -1) {
                    this.out.write(c);
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
        }
    }
}